home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
circuits
/
irsim-ca.2
/
irsim-ca
/
irsim-cap-9.2
/
src
/
irsim
/
hist_io.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-15
|
13KB
|
481 lines
/*
* *********************************************************************
* * Copyright (C) 1988, 1990 Stanford University. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. Stanford University *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
/*
* Routines to write and read history dump files
*/
#include <stdio.h>
#include "defs.h"
#include "net.h"
#include "ASSERT.h"
#include "bin_io.h"
#include "globals.h"
private char fh_header[] = "#HDUMP#\n"; /* first line of dump file */
private int dumph_version = 3;
/* define the number of bytes used to read/write history */
#define NB_HEADER ( sizeof( fh_header ) - 1 )
#define NB_NUMBER 4
#define NB_NDINDEX 4
#define NB_TIME 4
#define NB_PVAL 1
#define NB_RTIME 2
#define NB_DELAY 2
#define NB_EVAL 1
#define NB_VERSION 2
#define MAGIC_NUM( DELTA, NNODES ) ( ((DELTA) ^ (NNODES)) & 0xffff )
typedef struct
{
char header[ NB_HEADER ];
char hsize[ NB_NUMBER ];
char nnodes[ NB_NUMBER ];
char cur_delta[ NB_TIME ];
char magic[ NB_NUMBER ];
char version[ NB_VERSION ];
char time0[ NB_TIME ];
} File_Head;
#define Size_File_Head ( NB_HEADER + NB_NUMBER + NB_NUMBER + NB_TIME + \
NB_NUMBER + NB_VERSION + NB_TIME )
typedef struct /* format of history header, one per node */
{
char node[ NB_NDINDEX ]; /* node for which history follows */
char time[ NB_TIME ]; /* initial time (usually 0) */
char pval[ NB_PVAL ]; /* initial packed-value */
} Node_Head;
#define Size_Node_Head ( NB_NDINDEX + NB_TIME + NB_PVAL )
typedef struct /* format of each history entry */
{
char time[ NB_TIME ]; /* time of this change */
char rtime[ NB_RTIME ]; /* input rise time */
char delay[ NB_DELAY ]; /* associated delay */
char pval[ NB_PVAL ]; /* packed-value (inp, val, punt) */
char ptime[ NB_DELAY ]; /* punt time (only punted events) */
} File_Hist;
#define Size_File_Hist ( NB_TIME + NB_RTIME + NB_DELAY + NB_PVAL )
#define Size_Ptime ( NB_DELAY )
#define Size_PuntFile_Hist ( Size_File_Hist + Size_Ptime )
/* marks end of history. Must be same size as Size_File_Hist! */
typedef struct
{
char mark[ NB_TIME ]; /* marker, same for all nodes */
char npend[ NB_RTIME ]; /* # of pending events */
char dummy1[ NB_DELAY ]; /* just fill the space */
char dummy2[ NB_PVAL ];
} EndHist;
typedef struct /* format for pending events */
{
char cause[ NB_NDINDEX ];
char time[ NB_TIME ];
char delay[ NB_DELAY ];
char rtime[ NB_RTIME ];
char eval[ NB_EVAL ];
} File_Pend;
#define Size_File_Pend (NB_NDINDEX + NB_TIME + NB_DELAY + NB_RTIME + NB_EVAL)
/* macros to pack/unpack a value/inp/punt triplet from/to a byte */
#define PACK_VAL( H ) ( (H->inp << 5) | (H->punt << 4) | H->val )
#define GET_INP( PV ) ( (PV) >> 5 & 1 )
#define GET_VAL( PV ) ( (PV) & 0x7 )
#define IS_PUNT( PV ) ( (PV) & 0x10 )
private EndHist h_end =
{
{ '\0', '\0', '\0', '\040' }, /* mark */
{ '\0', '\0' }, /* npend */
{ '\0', '\0' }, /* dummy1 */
{ '\n' } /* dummy2 */
};
private int DumpNodeHist( nd, ndindx, fp )
nptr nd;
Ulong ndindx;
FILE *fp;
{
register hptr h;
Node_Head header;
File_Hist hist;
if( nd->nflags & (POWER_RAIL | ALIAS | MERGED) )
return( 0 );
PackBytes( header.node, ndindx, NB_NDINDEX );
h = &(nd->head);
PackBytes( header.time, h->time, NB_TIME );
PackBytes( header.pval, PACK_VAL( h ), NB_PVAL );
if( Fwrite( &header, Size_Node_Head, fp ) <= 0 )
goto abort;
for( h = h->next; h != last_hist; h = h->next )
{
PackBytes( hist.time, h->time, NB_TIME );
PackBytes( hist.pval, PACK_VAL( h ), NB_PVAL );
if( h->punt )
{
PackBytes( hist.delay, h->t.p.delay, NB_DELAY );
PackBytes( hist.rtime, h->t.p.rtime, NB_RTIME );
PackBytes( hist.ptime, h->t.p.ptime, NB_DELAY );
if( Fwrite( &hist, Size_PuntFile_Hist, fp ) <= 0 )
goto abort;
}
else
{
PackBytes( hist.delay, h->t.r.delay, NB_DELAY );
PackBytes( hist.rtime, h->t.r.rtime, NB_RTIME );
if( Fwrite( &hist, Size_File_Hist, fp ) <= 0 )
goto abort;
}
}
if( nd->events != NULL )
{
register evptr ev;
register int n;
File_Pend pending;
for( n = 0, ev = nd->events; ev != NULL; ev = ev->nlink, n++ );
PackBytes( h_end.npend, n, NB_RTIME );
if( Fwrite( &h_end, Size_File_Hist, fp ) <= 0 )
goto abort;
for( ev = nd->events; ev != NULL; ev = ev->nlink )
{
ndindx = Node2index( ev->p.cause );
PackBytes( pending.cause, ndindx, NB_NDINDEX );
PackBytes( pending.time, ev->ntime, NB_TIME );
PackBytes( pending.delay, ev->delay, NB_DELAY );
PackBytes( pending.rtime, ev->rtime, NB_RTIME );
PackBytes( pending.eval, ev->eval, NB_EVAL );
if( Fwrite( &pending, Size_File_Pend, fp ) <= 0 )
goto abort;
}
}
else
{
PackBytes( h_end.npend, 0, NB_RTIME );
if( Fwrite( &h_end, Size_File_Hist, fp ) <= 0 )
goto abort;
}
return( 0 );
abort:
lprintf( stderr, "can't write to file, history dump aborted\n" );
return( 1 );
}
private int WriteHistHeader( fd )
FILE *fd;
{
File_Head fh;
long mag;
mag = MAGIC_NUM( cur_delta, nnodes );
bcopy( fh_header, fh.header, NB_HEADER );
PackBytes( fh.hsize, GetHashSize(), NB_NUMBER );
PackBytes( fh.nnodes, nnodes, NB_NUMBER );
PackBytes( fh.cur_delta, cur_delta, NB_TIME );
PackBytes( fh.magic, mag, NB_NUMBER );
PackBytes( fh.version, dumph_version, NB_VERSION );
PackBytes( fh.time0, sim_time0, NB_TIME );
if( Fwrite( &fh, Size_File_Head, fd ) <= 0 )
return( -1 );
return( 0 );
}
private int ReadHistHead( fd, pNewTime, pTime0 )
FILE *fd;
long *pNewTime, *pTime0;
{
File_Head fh;
int n_nodes, hsize, n_version;
long newTime, magic, time0;
if( Fread( &fh, Size_File_Head, fd ) != Size_File_Head )
{
lprintf( stderr, "ReadHist: can't read file\n" );
return( -1 );
}
UnpackBytes( fh.version, n_version, NB_VERSION );
UnpackBytes( fh.hsize, hsize, NB_NUMBER );
UnpackBytes( fh.nnodes, n_nodes, NB_NUMBER );
UnpackBytes( fh.cur_delta, newTime, NB_TIME );
UnpackBytes( fh.magic, magic, NB_NUMBER );
UnpackBytes( fh.time0, time0, NB_TIME );
if( strncmp( fh_header, fh.header, NB_HEADER ) != 0 )
{
lprintf( stderr, "ReadHist: not a history dump file\n" );
return( -1 );
}
if( n_version != dumph_version )
{
lprintf( stderr, "ReadHist: Incompatible version: %d\n", n_version );
return( -1 );
}
if( (nnodes != n_nodes and nnodes != 0) or hsize != GetHashSize() or
magic != MAGIC_NUM( newTime, n_nodes ) )
{
lprintf( stderr, "ReadHist: incompatible or bad history dump\n" );
return( -1 );
}
*pNewTime = newTime;
*pTime0 = time0;
return( 0 );
}
public void DumpHist( fname )
char *fname;
{
FILE *fp;
if( (fp = fopen( fname, "w" )) == NULL )
{
lprintf( stderr, "can not open file '%s'\n", fname );
return;
}
if( WriteHistHeader( fp ) )
{
lprintf( stderr, "can't write to file '%s'\n", fname );
(void) fclose( fp );
return;
}
walk_net_index( DumpNodeHist, fp );
(void) fclose( fp );
}
private int rd_hist( fd, pnlist )
FILE *fd;
nptr *pnlist;
{
Node_Head head;
File_Hist hist;
EndHist *pe;
int inp, val, n, pval, delay, rtime;
Ulong ndindx;
nptr nd, ndlist;
long etime;
struct Event ev;
pe = (EndHist *) &hist;
ndlist = NULL;
while( Fread( &head, Size_Node_Head, fd ) == Size_Node_Head )
{
UnpackBytes( head.node, ndindx, NB_NDINDEX );
if( (nd = Index2node( ndindx )) == NULL )
{
lprintf( stderr, "history read aborted: could not find node\n" );
*pnlist = ndlist;
return( -1 );
}
if( nd->nflags & (POWER_RAIL | ALIAS) )
{
lprintf( stderr, "warning: %s should not be in history\n",
pnode( nd ) );
}
UnpackBytes( head.time, etime, NB_TIME );
UnpackBytes( head.pval, pval, NB_PVAL );
val = GET_VAL( pval );
inp = GET_INP( pval );
SetFirstHist( nd, val, inp, etime );
nd->n.next = ndlist;
ndlist = nd;
if( nd->head.next != last_hist )
FreeHistList( nd );
while( TRUE )
{
if( Fread( &hist, Size_File_Hist, fd ) != Size_File_Hist )
goto badfile;
if( bcmp( pe->mark, h_end.mark, NB_TIME ) == 0 )
break;
if( nd->nflags & (POWER_RAIL | ALIAS) )
continue;
UnpackBytes( hist.time, etime, NB_TIME );
UnpackBytes( hist.delay, delay, NB_DELAY );
UnpackBytes( hist.rtime, rtime, NB_RTIME );
UnpackBytes( hist.pval, pval, NB_PVAL );
val = GET_VAL( pval );
inp = GET_INP( pval );
ASSERT( delay < 60000 and delay >= 0 )
{
lprintf( stderr, "Error: Corrupted history entry:\n" );
lprintf( stderr, "\t%s time=%.1f delay=%.1f value=%c\n",
pnode( nd ), d2ns( etime ), d2ns( delay ), vchars[val] );
}
if( IS_PUNT( pval ) )
{
if( Fread( hist.ptime, Size_Ptime, fd ) != Size_Ptime )
goto badfile;
ev.eval = val;
ev.ntime = etime;
ev.delay = delay;
ev.rtime = rtime;
UnpackBytes( hist.ptime, delay, NB_DELAY );
etime -= delay;
AddPunted( nd, &ev, etime );
}
else
AddHist( nd, val, inp, etime, (long) delay, (long) rtime );
}
if( not (nd->nflags & POWER_RAIL) )
{
nd->npot = nd->curr->val;
if( nd->curr->inp )
nd->nflags |= INPUT;
}
while( nd->events != NULL ) /* get rid of any pending events */
free_event( nd->events );
UnpackBytes( pe->npend, n, NB_RTIME );
while( n != 0 )
{
File_Pend pend;
if( Fread( &pend, Size_File_Pend, fd ) != Size_File_Pend )
goto badfile;
UnpackBytes( pend.cause, ndindx, NB_NDINDEX );
UnpackBytes( pend.time, etime, NB_TIME );
UnpackBytes( pend.delay, delay, NB_DELAY );
UnpackBytes( pend.rtime, rtime, NB_RTIME );
UnpackBytes( pend.eval, val, NB_EVAL );
ASSERT( delay < 60000 and delay >= 0 )
{
lprintf( stdout, "Error: Corrupted history entry:\n" );
lprintf( stdout, "\t%s time=%.1f delay=%.1f value=%c [pnd]\n",
pnode( nd ), d2ns( etime ), d2ns( delay ), vchars[val] );
n--;
continue;
}
cur_node = Index2node( ndindx );
cur_delta = etime - delay; /* fake the delay */
enqueue_event( nd, val, (long) delay, (long) rtime );
n--;
}
}
*pnlist = ndlist;
return( 0 );
badfile:
lprintf( stderr, "premature eof on history file\n" );
*pnlist = ndlist;
return( -1 );
}
private void fix_transistors( nd )
register nptr nd;
{
register lptr l;
while( nd != NULL )
{
for( l = nd->ngate; l != NULL; l = l->next )
l->xtor->state = compute_trans_state( l->xtor );
nd = nd->n.next;
}
for( l = VDD_node->ngate; l != NULL; l = l->next )
l->xtor->state = compute_trans_state( l->xtor );
for( l = GND_node->ngate; l != NULL; l = l->next )
l->xtor->state = compute_trans_state( l->xtor );
}
public void ReadHist( fname )
char *fname;
{
FILE *fd;
long newTime, time0;
nptr ndlist;
if( (fd = fopen( fname, "r" )) == NULL )
{
lprintf( stderr, "can not open file '%s'\n", fname );
return;
}
if( ReadHistHead( fd, &newTime, &time0 ) )
{
(void) fclose( fd );
return;
}
ClearInputs();
if( rd_hist( fd, &ndlist ) )
{
nptr n;
for( n = ndlist; n != NULL; n = n->n.next )
{
FreeHistList( n ); /* undo any work done */
while( n->events != NULL )
free_event( n->events );
}
}
else
{
sim_time0 = time0;
cur_delta = newTime;
if( cur_delta > 0 )
NoInit();
if( VDD_node != NULL )
fix_transistors( ndlist );
}
(void) fclose( fd );
}